/***************************************************************************** * Copyright (c) 2010 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 MNM-Team, LMU Munich - initial API and implementation *****************************************************************************/ package eu.geclipse.eventgraph.tracereader.otf; import java.io.BufferedReader; import java.io.File; import java.io.FileInputStream; import java.io.FileReader; import java.io.IOException; import java.io.InputStreamReader; import java.util.ArrayList; import java.util.HashMap; import java.util.Map; import java.util.StringTokenizer; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.Status; import com.jcraft.jzlib.ZInputStream; /** * Reader for OTF Definition Files */ @SuppressWarnings("boxing") public class OTFDefinitionReader { private BufferedReader input; // trace information private int maxFunctionID; private int maxProcessGroupID; private String version = null; private String codename = null; private String creator = null; // DP private Map<Integer, String> processNames; // DPG private Map<Integer, String> processGroupNames; private Map<Integer, ArrayList<Integer>> processGroups; // DSF private Map<Integer, String> sourceFileNames; // DS private Map<Integer, Integer> sourceLineNumbers; private Map<Integer, Integer> sourceFileIDs; // DFG private Map<Integer, String> functionGroupNames; // DF private Map<Integer, String> functionNames; private Map<Integer, Integer> functionGroupIDs; private Map<Integer, Integer> functionSourceLocationIDs; // DCO private Map<Integer, String> collectiveOperationsNames; private Map<Integer, Integer> collectiveOperationsTypes; // private Map<Integer, CollectiveOperation> collectiveOperations; /** * Creates a new Definition Reader * * @param file (the .z ending is added automatically do not specify when creating File) * @throws IOException */ public OTFDefinitionReader( final File file ) throws IOException { this.maxFunctionID = 0; this.maxProcessGroupID = 0; this.version = null; this.codename = null; this.creator = null; // DP this.processNames = new HashMap<Integer, String>(); // DPG this.processGroupNames = new HashMap<Integer, String>(); this.processGroups = new HashMap<Integer, ArrayList<Integer>>(); // DSF this.sourceFileNames = new HashMap<Integer, String>(); // DS this.sourceLineNumbers = new HashMap<Integer, Integer>(); this.sourceFileIDs = new HashMap<Integer, Integer>(); // DFG this.functionGroupNames = new HashMap<Integer, String>(); // DF this.functionNames = new HashMap<Integer, String>(); this.functionGroupIDs = new HashMap<Integer, Integer>(); this.functionSourceLocationIDs = new HashMap<Integer, Integer>(); // DCO this.collectiveOperationsNames = new HashMap<Integer, String>(); this.collectiveOperationsTypes = new HashMap<Integer, Integer>(); if( file.exists() ) { this.input = new BufferedReader( new FileReader( file ) ); } else { File zFile = new File( file.getParentFile(), file.getName() + ".z" ); //$NON-NLS-1$ // jcraft inflater this.input = new BufferedReader( new InputStreamReader( new ZInputStream( new FileInputStream( zFile ) ) ) ); // SUN inflater, suffers from java bug # 4040920 // this.input = new BufferedReader( new InputStreamReader( new InflaterInputStream( new FileInputStream( zFile ) ) ) ); } read(); } private void read() throws IOException { String line; while( ( line = this.input.readLine() ) != null ) { // Version if( line.startsWith( "DV" ) ) { //$NON-NLS-1$ int start = line.indexOf( "\"" ); //$NON-NLS-1$ int end = line.lastIndexOf( "\"" ); //$NON-NLS-1$ this.version = line.substring( 2, start ); this.codename = line.substring( start + 1, end ); } // Creator else if( line.startsWith( "DCR" ) ) { //$NON-NLS-1$ this.creator = line.substring( 4, line.length() - 1 ); } // Process Names else if( line.startsWith( "DP" ) && ( Character.isDigit( line.charAt( 2 ) ) || Character.isLowerCase( line.charAt( 2 ) ) ) ) { //$NON-NLS-1$ Integer processId = Integer.valueOf( line.substring( 2, line.indexOf( "NM" ) ), 16 ); //$NON-NLS-1$ String processName = line.substring( line.indexOf( "NM" ) + 3, line.length() - 1 ); //$NON-NLS-1$ this.processNames.put( processId, processName ); } // Process Group else if( line.startsWith( "DPG" ) && ( Character.isDigit( line.charAt( 3 ) ) || Character.isLowerCase( line.charAt( 3 ) ) ) ) { //$NON-NLS-1$ Integer processGroupID = Integer.valueOf( line.substring( 3, line.indexOf( 'M' ) ), 16 ); String processIDString = line.substring( line.indexOf( 'M' ) + 1, line.indexOf( "NM" ) ); //$NON-NLS-1$ String processGroupName = line.substring( line.indexOf( "NM" ) + 3, line.length() - 1 ); //$NON-NLS-1$ StringTokenizer stringTokenizer = new StringTokenizer( processIDString, "," ); //$NON-NLS-1$ ArrayList<Integer> processGroup = new ArrayList<Integer>(); while( stringTokenizer.hasMoreElements() ) { processGroup.add( Integer.parseInt( stringTokenizer.nextToken(), 16 ) ); } this.processGroups.put( processGroupID, processGroup ); this.processGroupNames.put( processGroupID, processGroupName ); this.maxProcessGroupID = Math.max( this.maxProcessGroupID, processGroupID ); } // Source Files else if( line.startsWith( "DSF" ) && ( Character.isDigit( line.charAt( 3 ) ) || Character.isLowerCase( line.charAt( 3 ) ) ) ) { //$NON-NLS-1$ Integer sourceId = Integer.valueOf( line.substring( 3, line.indexOf( "NM" ) ), 16 ); //$NON-NLS-1$ String sourceFileName = line.substring( line.indexOf( "NM" ) + 3, line.length() - 1 ); //$NON-NLS-1$ this.sourceFileNames.put( sourceId, sourceFileName ); } // Source Locations else if( line.startsWith( "DS" ) && ( Character.isDigit( line.charAt( 2 ) ) || Character.isLowerCase( line.charAt( 2 ) ) ) ) { //$NON-NLS-1$ Integer locationID = Integer.valueOf( line.substring( 2, line.indexOf( 'F' ) ), 16 ); Integer sourceFileID = Integer.valueOf( line.substring( line.indexOf( 'F' ) + 1, line.indexOf( "LN" ) ), 16 ); //$NON-NLS-1$ Integer sourceLineNumber = Integer.valueOf( line.substring( line.indexOf( "LN" ) + 2, line.length() ), 16 ); //$NON-NLS-1$ this.sourceLineNumbers.put( locationID, sourceLineNumber ); this.sourceFileIDs.put( locationID, sourceFileID ); } // Function Groups else if( line.startsWith( "DFG" ) && ( Character.isDigit( line.charAt( 3 ) ) || Character.isLowerCase( line.charAt( 3 ) ) ) ) { //$NON-NLS-1$ Integer groupId = Integer.valueOf( line.substring( 3, line.indexOf( "NM" ) ), 16 ); //$NON-NLS-1$ String groupName = line.substring( line.indexOf( "NM" ) + 3, line.length() - 1 ); //$NON-NLS-1$ this.functionGroupNames.put( groupId, groupName ); } // Functions else if( line.startsWith( "DF" ) && ( Character.isDigit( line.charAt( 2 ) ) || Character.isLowerCase( line.charAt( 2 ) ) ) ) { //$NON-NLS-1$ int sourceLocationID = -1; Integer functionID = Integer.valueOf( line.substring( 2, line.indexOf( 'G' ) ), 16 ); Integer functionGroupId = Integer.valueOf( line.substring( line.indexOf( 'G' ) + 1, line.indexOf( 'N' ) ), 16 ); String functionName = line.substring( line.indexOf( '\"' ) + 1, line.lastIndexOf( '\"' ) ); int sourcelocation = line.lastIndexOf( 'X' ); if( sourcelocation != -1 ) { sourceLocationID = Integer.valueOf( line.substring( sourcelocation + 1 ), 16 ); } this.functionNames.put( functionID, functionName ); this.functionGroupIDs.put( functionID, functionGroupId ); this.functionSourceLocationIDs.put( functionID, sourceLocationID ); this.maxFunctionID = Math.max( this.maxFunctionID, functionID ); } // Collective Operations else if( line.startsWith( "DCO" ) && ( Character.isDigit( line.charAt( 3 ) ) || Character.isLowerCase( line.charAt( 3 ) ) ) ) { //$NON-NLS-1$ Integer operationId = Integer.valueOf( line.substring( 3, line.indexOf( "NM" ) ), 16 ); //$NON-NLS-1$ String operationName = line.substring( line.indexOf( "NM" ) + 3, line.lastIndexOf( '\"' ) ); //$NON-NLS-1$ Integer operationType = Integer.valueOf( line.substring( line.indexOf( 'Y', line.lastIndexOf( '\"' ) ) + 1 ), 16 ); this.collectiveOperationsNames.put( operationId, operationName ); // 0 scan // 1 one sided, barrier // 2 scatter // 4 gather, reduce // 4 all , exscan this.collectiveOperationsTypes.put( operationId, operationType ); } // Unsupported Definition else { Activator.getDefault().getLog().log( new Status( IStatus.WARNING, Activator.PLUGIN_ID, "Unsupported OTF Definition Type: " + line ) ); } } } /** * Returns the OTF version of the trace * * @return OTF Version */ public String getVersion() { return this.version; } /** * Returns the codename of the OTF version of the trace * * @return Codename */ public String getCodename() { return this.codename; } /** * Returns the name of the tool used to create the trace * * @return Name of the tool used to create the trace */ public String getCreator() { return this.creator; } /** * Returns the process name for the specified process id * * @param processId * @return process name */ public String getProcessName( final int processId ) { return this.processNames.get( processId ); } /** * Returns the process group members * * @param groupId * @return process group members */ public Integer[] getProcessGroup( final int groupId ) { return this.processGroups.get( groupId ).toArray( new Integer[ 0 ] ); } /** * Returns the name of the process group * * @param groupId * @return process group */ public String getProcessGroupName( final int groupId ) { return this.processGroupNames.get( groupId ); } /** * Returns the Name of the sourcefile * * @param sourceFileID * @return Name of sourcefile */ public String getSourceFileName( final int sourceFileID ) { return this.sourceFileNames.get( sourceFileID ); } /** * Returns the line number of the source location * * @param sourceLocationID * @return line number */ public int getSourceLineNumber( final int sourceLocationID ) { return this.sourceLineNumbers.get( sourceLocationID ); } /** * Returns the source file id for the source location * * @param sourceLocationID * @return source file id */ public int getSourceFileID( final int sourceLocationID ) { return this.sourceFileIDs.get( sourceLocationID ); } /** * Returns the group name for the specified function group id * * @param functionGroupID * @return name of the according group */ public String getFunctionGroupName( final int functionGroupID ) { return this.functionGroupNames.get( functionGroupID ); } /** * Returns the function name for the specified function id * * @param functionID * @return name of the according function */ public String getFunctionName( final int functionID ) { return this.functionNames.get( functionID ); } /** * Returns the function group id for the specified function id * * @param functionID * @return function group id */ public int getFunctionGroupID( final int functionID ) { Integer id = this.functionGroupIDs.get( functionID ); return ( id == null ) ? -1 : id; } /** * Returns the source location id for the specified function id * * @param functionID * @return source location id */ public int getSourceLocationID( final int functionID ) { int result = -1; Integer id = this.functionSourceLocationIDs.get( functionID ); if( id != null ) { result = id.intValue(); } return result; } /** * Returns the names of the function groups * * @return function group names */ public String[] getFunctionGroupNames() { return this.functionGroupNames.values().toArray( new String[0] ); } /** * Returns the names of the process groups * * @return process group names */ public String[] getProcessGroupNames() { return this.processGroupNames.values().toArray( new String[0] ); } protected int getMaxFunctionID() { return this.maxFunctionID; } protected int getMaxProcessGroupID() { return this.maxProcessGroupID; } }