/***************************************************************************** * Copyright (c) 2006, 2008 g-Eclipse Consortium * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Initial development of the original code was made for the * g-Eclipse project founded by European Union * project number: FP6-IST-034327 http://www.geclipse.eu/ * * Contributors: * Christof Klausecker GUP, JKU - initial API and implementation *****************************************************************************/ package eu.geclipse.traceview.nope.tracereader; import java.io.BufferedInputStream; import java.io.DataInputStream; import java.io.EOFException; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; import java.util.HashMap; import java.util.Vector; import org.eclipse.core.runtime.IStatus; import org.eclipse.ui.views.properties.IPropertyDescriptor; import org.eclipse.ui.views.properties.PropertyDescriptor; import eu.geclipse.traceview.EventType; import eu.geclipse.traceview.nope.Activator; import eu.geclipse.traceview.utils.AbstractProcessFileCache; /** * NOPE (NOndeterministic Program Evaluator) Process */ final public class Process extends AbstractProcessFileCache { /* StatusByte */ /** a processors byte ordering */ public static byte trcLittleEndian = ( byte )0x80; /** a processors byte ordering */ public static byte trcBigEndian = ( byte )0x00; /** completeness of a trace */ public static byte trcPartial = ( byte )0x00; /** completeness of a trace */ public static byte trcTotal = ( byte )0x40; /** source file information added */ public static byte trcWithout = ( byte )0x00; /** source file information added */ public static byte trcWith = ( byte )0x20; /** level of monitor implementation */ public static byte trcFunctions = ( byte )0x00; /** level of monitor implementation */ public static byte trcMacros = ( byte )0x08; /** level of monitor implementation */ public static byte trcAssembler = ( byte )0x10; /** level of monitor implementation */ public static byte trcTraps = ( byte )0x18; /** amount of traced event data */ public static byte trcMinimum = ( byte )0x00; /** amount of traced event data */ public static byte trcMedium = ( byte )0x02; /** amount of traced event data */ public static byte trcMaximum = ( byte )0x06; /** hardware and OS used */ public static byte trcNCUBE = ( byte )0x00; /** hardware and OS used */ public static byte trcPARSYTEC = ( byte )0x01; /** boolean values */ public static byte trcFALSE = ( byte )0x00; /** boolean values */ public static byte trcTRUE = ( byte )0x80; /* event types */ /** no event, end of trace file */ public static byte trcNoEv = 0x00; /** receive event (nread, nreadp) */ public static byte trcRecv = 0x01; /** send event (nwrite, nwritep) */ public static byte trcSend = 0x02; /** test event (ntest) */ public static byte trcTest = 0x03; /** internal event: new source file */ public static byte trcSourceLine = 0x04; /** event of type "others", e.g. nsync */ public static byte trcOthers = 0x05; /** trace event, e.g. monULONGTRACE */ public static byte trcTrace = 0x07; /* event subtypes */ /** variable inspection type */ public static byte trcTVarInsp = 0x00; /** switch flushing - type */ public static byte trcTFlush = 0x01; /** activate/deactivate mon */ public static byte trcTOnOff = 0x02; /** record time stamp (abs) */ public static byte trcTTimer = 0x03; /** message queue trace */ public static byte trcTMsgQueue = 0x04; /** repeated test event type */ public static byte trcTTestLoop = 0x05; /** array inspection type */ public static byte trcTArrInsp = 0x06; private static final String PROP_ID = "Process.Id"; //$NON-NLS-1$ private static IPropertyDescriptor[] descriptors; /* * Information of from the File */ private String traceFileName; private long fileSize; /* Information from the Header */ private int version; private boolean isTrcBigEndian; private int traceAmount; private boolean source; private int level; private int dataAmount; private int multiprocessor; private String filename; private String arguments; private int monStrat; private int monPModel; private int monStor; private int monError; private int monFlush; private int monBuffer; private long runTimeStart; /* Information from the Event */ private HashMap<Integer, Integer> ignoreCounts = new HashMap<Integer, Integer>(); private int previousLogicalClock = -1; private boolean debug = false; // private FileProcessCache processCache; // private List<String> sourceFilenames; private int sourceFilenameIndex; private int[] initialVectorClock; private boolean supportsVectorClocks; // private FileInputStream fileInputStream = null; private DataInputStream dataInputStream = null; /** Process */ static { descriptors = new IPropertyDescriptor[]{ new PropertyDescriptor( PROP_ID, "Process ID" ), //$NON-NLS-1$ }; } protected Process( final InputStream inputStream, final String filename, final long filesize, final int processId, final boolean hasCache, final Trace trace ) { super( trace, processId ); // initialise vectorclocks this.supportsVectorClocks = ( ( Trace )trace ).supportsVectorClocks(); if ( supportsVectorClocks ) { this.initialVectorClock = new int[ trace.getNumberOfProcesses() ]; for( int i = 0; i < this.initialVectorClock.length; i++ ) { this.initialVectorClock[ i ] = -1; } } try { // in case the cache does not exist InputStream bufferedInputStream = new BufferedInputStream( inputStream ); this.dataInputStream = new DataInputStream( bufferedInputStream ); this.traceFileName = filename; this.fileSize = filesize; /* * header information */ readHeader(); /* * debug output */ if( this.debug ) { headerInfo(); } /* * read the events */ if( !hasCache ) { Event event = null; while( ( event = readEvent() ) != null ) { if( this.debug ) { eventInfo( event ); } } } } catch( EOFException eofException ) { // do nothing (because of unsupported event types) } catch( FileNotFoundException fileNotFoundException ) { Activator.logException( fileNotFoundException ); } catch( IOException ioException ) { Activator.logException( ioException ); } } // ***************************************************** // * IPropertySource // ***************************************************** /* * (non-Javadoc) * * @see org.eclipse.ui.views.properties.IPropertySource#getPropertyDescriptors() */ @Override public IPropertyDescriptor[] getPropertyDescriptors() { return descriptors; } /* * (non-Javadoc) * * @see org.eclipse.ui.views.properties.IPropertySource#getPropertyValue(java.lang.Object) */ @Override public Object getPropertyValue( final Object id ) { return Integer.valueOf( this.getProcessId() ); } // ***************************************************** // * IProcess // ***************************************************** /* * (non-Javadoc) * * @see eu.geclipse.traceview.IProcess#getEventByLogicalClock(int) */ public Event getEventByLogicalClock( final int index ) throws IndexOutOfBoundsException { Event result = null; if( index <= this.getMaximumLogicalClock() ) { if( this.supportsVectorClocks ) result = new VecEvent( index, this ); else result = new Event( index, this ); } return result; } private int readInt() throws IOException { int result = this.dataInputStream.readInt(); if( !this.isTrcBigEndian ) { result = Integer.reverseBytes( result ); } return result; } private long readLong() throws IOException { long result = this.dataInputStream.readLong(); if( !this.isTrcBigEndian ) { result = Long.reverseBytes( result ); } return result; } private void debugOutput( final String message ) { // System.out.println( message ); } private void headerInfo() { debugOutput( "version of trace file : " + this.version ); //$NON-NLS-1$ debugOutput( "processor : " + this.processId ); //$NON-NLS-1$ debugOutput( "filename: : " + this.traceFileName ); //$NON-NLS-1$ debugOutput( "filesize: : " + this.fileSize ); //$NON-NLS-1$ if( this.isTrcBigEndian ) { debugOutput( "byte ordering : big endian" ); //$NON-NLS-1$ } else { debugOutput( "byte ordering : little endian" ); //$NON-NLS-1$ } debugOutput( "trace amount : " + this.traceAmount ); //$NON-NLS-1$ debugOutput( "source switch : " + this.source ); //$NON-NLS-1$ debugOutput( "level of impl : " + this.level ); //$NON-NLS-1$ debugOutput( "data amount : " + this.dataAmount ); //$NON-NLS-1$ debugOutput( "multiprocessor : " + this.multiprocessor ); //$NON-NLS-1$ debugOutput( "program name : " + this.filename ); //$NON-NLS-1$ debugOutput( "program args : " + this.arguments ); //$NON-NLS-1$ debugOutput( "run time start : " + this.runTimeStart ); //$NON-NLS-1$ debugOutput( "mon strategy : " + this.monStrat ); //$NON-NLS-1$ debugOutput( "model of prog : " + this.monPModel ); //$NON-NLS-1$ debugOutput( "error mon : " + this.monError ); //$NON-NLS-1$ debugOutput( "flushing mode : " + this.monFlush ); //$NON-NLS-1$ debugOutput( "file buffer : " + this.monBuffer ); //$NON-NLS-1$ debugOutput( "tracing disk : " + this.monStor ); //$NON-NLS-1$ } private void eventInfo( final Event event ) { debugOutput( "Type: " + event.getType() ); //$NON-NLS-1$ debugOutput( "" ); debugOutput( "traceComm.blocking: " + event.getBlocking() ); //$NON-NLS-1$ debugOutput( "traceComm.commname: " + event.getSubType() ); //$NON-NLS-1$ debugOutput( "" ); debugOutput( "(traceComm.supposed)->partner: " //$NON-NLS-1$ + event.getSupposedPartnerProcess() ); debugOutput( "(traceComm.supposed)->msgtype: " //$NON-NLS-1$ + event.getSupposedMessageType() ); debugOutput( "(traceComm.supposed)->msglength: " //$NON-NLS-1$ + event.getSupposedMessageLength() ); debugOutput( "" ); debugOutput( "(traceComm.accepted)->partner: " //$NON-NLS-1$ + event.getAcceptedPartnerProcess() ); debugOutput( "(traceComm.accepted)->msgtype: " //$NON-NLS-1$ + event.getAcceptedMessageType() ); debugOutput( "(traceComm.accepted)->msglength: " //$NON-NLS-1$ + event.getAcceptedMessageLength() ); debugOutput( "" ); debugOutput( "traceTime.log: " + event.getLogicalClock() ); //$NON-NLS-1$ debugOutput( "traceTime.partnerLog: " //$NON-NLS-1$ + event.getPartnerLogicalClock() ); debugOutput( "traceTime.timeStart: " + event.getPhysicalStartClock() ); //$NON-NLS-1$ debugOutput( "traceTime.timeStop: " + event.getPhysicalStopClock() ); //$NON-NLS-1$ debugOutput( "" ); debugOutput( "traceExt.line: " + event.getSourceLineNumber() ); //$NON-NLS-1$ debugOutput( "traceExt.file: " + event.getSourceFilename() ); //$NON-NLS-1$ } void readHeader() throws IOException { this.version = this.dataInputStream.readInt(); byte statusByte = this.dataInputStream.readByte(); this.isTrcBigEndian = ( statusByte & trcLittleEndian ) == 0x00; if( !this.isTrcBigEndian ) this.version = Integer.reverseBytes( this.version ); this.traceAmount = ( statusByte & trcTotal ); this.source = ( statusByte & trcWith ) != 0x00; this.level = ( statusByte & trcTraps ); this.dataAmount = ( statusByte & trcMaximum ); this.multiprocessor = ( statusByte & trcPARSYTEC ); byte[] filenameArray = new byte[ readInt() ]; this.dataInputStream.read( filenameArray ); this.filename = new String( filenameArray ); byte[] argumentsArray = new byte[ readInt() ]; this.dataInputStream.read( argumentsArray ); this.arguments = new String( argumentsArray ); this.monStrat = readInt(); this.monPModel = readInt(); this.monStor = readInt(); this.monError = readInt(); this.monFlush = readInt(); this.monBuffer = readInt(); this.runTimeStart = readLong(); } private Event readEvent() throws IOException { Event event = null; byte fileByte = 0; fileByte = this.dataInputStream.readByte(); int traceType = ( fileByte & ( ~trcTRUE ) ); if( traceType == trcRecv || traceType == trcSend || traceType == trcTest ) { event = readReceiveSendTestEvent( traceType ); } else if( traceType == trcSourceLine ) { readSourceEvent(); event = readEvent(); } else if( traceType == trcOthers ) { Activator.logMessage( IStatus.WARNING, "unimplemented event type: trcOthers" ); //$NON-NLS-1$ } else if( traceType == trcTrace ) { event = readTraceEvent(); } else { Activator.logMessage( IStatus.ERROR, "unknown event type" ); //$NON-NLS-1$ } return event; } private Event readReceiveSendTestEvent( final int traceType ) throws IOException { this.previousLogicalClock++; this.setMaximumLogicalClock( this.previousLogicalClock ); Event event = getEventByLogicalClock( this.previousLogicalClock ); event.setLamportClock( -1 ); if( this.supportsVectorClocks ) ((VecEvent)event).setVectorClock( this.initialVectorClock ); event.setPartnerLamportClock( -1 ); event.setType( getEventType( traceType ) ); // blocking int blocking = ( traceType & trcTRUE ); event.setBlocking( blocking ); event.setSubType( this.dataInputStream.readUnsignedByte() ); if( this.source ) { event.setSourceFilenameIndex( this.sourceFilenameIndex ); event.setSourceLineNumber( readInt() ); if( this.ignoreCounts.get( Integer.valueOf( event.getSourceLineNumber() ) ) != null ) { event.setIgnoreCount( this.ignoreCounts.get( Integer.valueOf( event.getSourceLineNumber() ) ) .intValue() + 1 ); this.ignoreCounts.put( Integer.valueOf( event.getSourceLineNumber() ), Integer.valueOf( event.getIgnoreCount() ) ); } else { this.ignoreCounts.put( Integer.valueOf( event.getSourceLineNumber() ), Integer.valueOf( 0 ) ); event.setIgnoreCount( 0 ); } // source tab this.dataInputStream.skipBytes( 1 ); } if( this.dataAmount == trcMedium || this.dataAmount == trcMaximum ) { event.setPhysicalStartClock( readInt() ); } if( this.dataAmount == trcMaximum ) { event.setSupposedPartnerProcess( readInt() ); event.setSupposedMessageType( readInt() ); event.setSupposedMessageLength( readInt() ); } event.setAcceptedPartnerProcess( readInt() ); event.setAcceptedMessageType( readInt() ); event.setAcceptedMessageLength( readInt() ); readInt(); // int logicalClock = // if( logicalClock != this.previousLogicalClock ) { // System.out.println( "logical clock mismatch: " // + logicalClock // + " " // + this.previousLogicalClock ); // } event.setPartnerLogicalClock( readInt() ); if( this.dataAmount == trcMaximum ) { event.setPhysicalStopClock( readInt() ); } // this.previousLogicalClock = tmpEvent.getLogicalClock(); return event; } private void readSourceEvent() throws IOException { int len = this.dataInputStream.readUnsignedByte(); byte[] srcfile = new byte[ len ]; this.dataInputStream.read( srcfile ); String sourceFilename = new String( srcfile ); this.sourceFilenameIndex = addSourceFilename( sourceFilename ); } private Event readTraceEvent() throws IOException { Event event = null; byte subtype = this.dataInputStream.readByte(); if( subtype == trcTVarInsp ) { Activator.logMessage( IStatus.WARNING, "subtype trcTVarInsp not supported" ); //$NON-NLS-1$ } else if( subtype == trcTFlush ) { Activator.logMessage( IStatus.WARNING, "subtype trcTFlush not supported" ); //$NON-NLS-1$ } else if( subtype == trcTOnOff ) { event = readEventSubTypeTOnOff(); } else if( subtype == trcTTimer ) { Activator.logMessage( IStatus.WARNING, "subtype trcTTimer not supported" ); //$NON-NLS-1$ } else if( subtype == trcTMsgQueue ) { Activator.logMessage( IStatus.WARNING, "subtype trcTMsgQueue not supported" ); //$NON-NLS-1$ } else if( subtype == trcTTestLoop ) { Activator.logMessage( IStatus.WARNING, "subtype trcTTestLoop not supported" ); //$NON-NLS-1$ } else if( subtype == trcTArrInsp ) { event = readEventSubTypeTArrInsp(); } return event; } @SuppressWarnings("unused") private Event readEventSubTypeTOnOff() throws IOException { // TODO better support for this event type this.previousLogicalClock++; this.setMaximumLogicalClock( this.previousLogicalClock ); Event event = getEventByLogicalClock( this.previousLogicalClock ); event.setLamportClock( -1 ); if( this.supportsVectorClocks ) ((VecEvent)event).setVectorClock( this.initialVectorClock ); event.setPartnerLamportClock( -1 ); event.setType( EventType.OTHER ); event.setAcceptedPartnerProcess( this.processId ); int trcSrcLine = -1; int trcSrcTab = -1; if( this.source ) { trcSrcLine = readInt(); trcSrcTab = this.dataInputStream.readByte(); } int timeStart = -1; // only guessed that it is the same way as with the other events // (dataamount) if( this.dataAmount == trcMedium || this.dataAmount == trcMaximum ) { timeStart = readInt(); } this.dataInputStream.skipBytes( 5 ); int size = readInt(); int noe = readInt(); int timeStop = readInt(); this.dataInputStream.readUnsignedByte(); this.dataInputStream.skip( 4 ); return event; } @SuppressWarnings("unused") private Event readEventSubTypeTArrInsp() throws IOException { // TODO better support for this event type this.previousLogicalClock++; ArrayEvent event = new ArrayEvent( this.previousLogicalClock, this ); event.setLamportClock( -1 ); event.setPartnerLamportClock( -1 ); event.setType( EventType.OTHER ); event.setAcceptedPartnerProcess( this.processId ); if( this.source ) { event.setSourceLineNumber( readInt() ); this.dataInputStream.skipBytes( 1 ); } if( this.dataAmount == trcMedium || this.dataAmount == trcMaximum ) { event.setPhysicalStartClock( readInt() ); } this.dataInputStream.skipBytes( 5 ); int size = readInt(); int noe = readInt(); event.setPhysicalStopClock( readInt() ); int elemType = this.dataInputStream.readUnsignedByte(); int elemSize = readInt(); int numDims = readInt(); int numPADims = readInt(); Vector<Integer> arrSize = new Vector<Integer>(); for( int v = 0; v < numDims; v++ ) { arrSize.add( Integer.valueOf( readInt() ) ); } Vector<Integer> paSize = new Vector<Integer>(); for( int v = 0; v < numDims; v++ ) { paSize.add( Integer.valueOf( readInt() ) ); } Vector<Integer> dist = new Vector<Integer>(); for( int v = 0; v < numDims; v++ ) { dist.add( Integer.valueOf( readInt() ) ); } Vector<Integer> remainder = new Vector<Integer>(); for( int v = 0; v < numDims; v++ ) { remainder.add( Integer.valueOf( readInt() ) ); } StringBuffer test = new StringBuffer(); char b = 0; do { b = ( char )this.dataInputStream.readByte(); test.append( b ); } while( b != 0 ); StringBuffer test2 = new StringBuffer(); do { b = ( char )this.dataInputStream.readByte(); test2.append( b ); } while( b != 0 ); return event; } /** * Converts event type from TrcUtil constant to {@link EventType} enum * * @param type TrcUtil constant. * @return EventType matching the TrcUtil constant. */ private EventType getEventType( final int type ) { EventType evType = null; if( type == 1 ) evType = EventType.RECV; else if( type == 2 ) evType = EventType.SEND; else if( type == 3 ) evType = EventType.TEST; else if( type == 4 ) evType = EventType.OTHER; return evType; } }