analyzetool/commandlineengine/src/CATParseTraceFile.cpp
changeset 22 a009639409f5
child 49 7fdc9a71d314
equal deleted inserted replaced
17:67c6ff54ec25 22:a009639409f5
       
     1 /*
       
     2 * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description:  Definitions for the class CATParseTraceFile.
       
    15 *
       
    16 */
       
    17 
       
    18 
       
    19 #include "../inc/ATCommonDefines.h"
       
    20 #include "../inc/CATParseTraceFile.h"
       
    21 #include "../inc/catdatasaver.h"
       
    22 #include "../inc/CATDatParser.h"
       
    23 
       
    24 #include <time.h>
       
    25 
       
    26 #define MAIN_ID "PCSS"
       
    27 #define ALLOC_ID "ALLOC" // < V.1.6 allocation.
       
    28 #define ALLOCH_ID "ALLOCH" // Header of multi message allocation.
       
    29 #define ALLOCF_ID "ALLOCF" // Fragment of multi message allocation.
       
    30 #define FREE_ID "FREE"
       
    31 #define FREEH_ID "FREEH" // Header of multi message free.
       
    32 #define FREEF_ID "FREEF" // Fragment of multi message free.
       
    33 #define HANDLE_LEAK_ID "HANDLE_LEAK"
       
    34 
       
    35 const string ERROR_OCCURED = "ERROR_OCCURED"; // Error messages.
       
    36 const string INCORRECT_ATOOL_VERSION = "INCORRECT_ATOOL_VERSION";
       
    37 /**
       
    38 * Invalid characters in trace file line content.
       
    39 * These will be filtered out before actuall parsing of line.
       
    40 10 = LF
       
    41 13 = CR
       
    42 124 = |
       
    43 */
       
    44 const char cINVALID_TRACE_FILE_CHARS[] = { 10, 13, 124 };
       
    45 
       
    46 // -----------------------------------------------------------------------------
       
    47 // CATParseTraceFile::CATParseTraceFile
       
    48 // Constructor.
       
    49 // -----------------------------------------------------------------------------
       
    50 CATParseTraceFile::CATParseTraceFile()
       
    51 {
       
    52 	LOG_FUNC_ENTRY("CATParseTraceFile::CATParseTraceFile");
       
    53 	m_DataSaver.SetPrintFlag( false );
       
    54 }
       
    55 
       
    56 // -----------------------------------------------------------------------------
       
    57 // CATParseTraceFile::StartParse
       
    58 // Main function to start trace parsing.
       
    59 // -----------------------------------------------------------------------------
       
    60 bool CATParseTraceFile::StartParse( const char* pFileName, const char* pOutputFileName )
       
    61 {
       
    62 	LOG_FUNC_ENTRY("CATParseTraceFile::StartParse");
       
    63 
       
    64 	// Return value, will be changed to true if process start found.
       
    65 	bool bRet = false;
       
    66 
       
    67 	// Check pointers
       
    68 	if ( pFileName == NULL  )
       
    69 		return bRet;
       
    70 
       
    71 	if( pOutputFileName == NULL )
       
    72 		return bRet;
       
    73 
       
    74 	if ( ! FileExists( pFileName ) )
       
    75 	{
       
    76 		cout << AT_MSG << "Error, input file \""
       
    77 			<< pFileName
       
    78 			<< "\" does not exist." << endl;
       
    79 		return bRet;
       
    80 	}
       
    81 
       
    82 	// Open data file
       
    83 	ifstream in( pFileName );
       
    84 
       
    85 	// Check file opened ok
       
    86 	if ( !in.good() )
       
    87 		return false;
       
    88 
       
    89 	// Get stream size
       
    90 	size_t streamPos = in.tellg();
       
    91 	in.seekg( 0, ios::end);
       
    92 	size_t streamEnd = in.tellg();
       
    93 	in.seekg( 0, ios::beg);
       
    94 
       
    95 	//Origianl characters (not filtered).
       
    96 	char cOriginalLineFromFile[MAX_LINE_LENGTH];
       
    97 
       
    98 	vector<CProcessData> vProcessList;
       
    99 	int iProcessIDinList = -1;
       
   100 
       
   101 	bool bFileVersionSaved = false;
       
   102 	// Read lines
       
   103 	while( streamPos < streamEnd )
       
   104 	{
       
   105 		// Get one line. Don't use stream flags to determinate end of file
       
   106 		// it can be found too early because trace can contain "anything".
       
   107 		in.getline( cOriginalLineFromFile, MAX_LINE_LENGTH );
       
   108 		
       
   109 		// Refresh position
       
   110 		streamPos = in.tellg();
       
   111 
       
   112 		// Check has bad bit flag raised. (i.e. device problems reading data)
       
   113 		if( in.bad() )
       
   114 		{
       
   115 			cout << AT_MSG << "Integrity error reading the trace file, reading aborted." << endl;
       
   116 			return false;
       
   117 		}
       
   118 		//Filtered characters.
       
   119 		char cLineFromFile[MAX_LINE_LENGTH];
       
   120 		char* pFiltered = cLineFromFile;
       
   121 
       
   122 		//Loop thru all characters in original line.
       
   123 		for( size_t i = 0 ; cOriginalLineFromFile[i] != 0 ; i++ )
       
   124 		{
       
   125 			//If character in line is not in invalid character array append it
       
   126 			//to filtered line.
       
   127 			if ( strchr( cINVALID_TRACE_FILE_CHARS, cOriginalLineFromFile[i] ) == 0 )
       
   128 					*pFiltered++ =  cOriginalLineFromFile[i];
       
   129 		}
       
   130 		*pFiltered++ = 0; //Add null termination to filtered line.
       
   131 
       
   132 		if( !bFileVersionSaved && *cLineFromFile != 0 )
       
   133 		{
       
   134 			bFileVersionSaved = true;
       
   135 			m_DataSaver.AddString( AT_DATA_FILE_VERSION );
       
   136 			m_DataSaver.AddLineToLast();
       
   137 		}
       
   138 
       
   139 		// Is there main ID?
       
   140 		if( strstr( cLineFromFile, MAIN_ID ) != NULL )
       
   141 		{
       
   142 			string sRestOfLine( cLineFromFile );
       
   143 			string sTemp;
       
   144 
       
   145 			// Delete all characters before main ID
       
   146 			sRestOfLine.erase( 0, sRestOfLine.find( MAIN_ID ) );
       
   147 
       
   148 			// Get main ID
       
   149 			sTemp = GetStringUntilNextSpace( sRestOfLine );
       
   150 
       
   151 			// Is there more data in line?
       
   152 			if( sRestOfLine.empty() )
       
   153 			{
       
   154 				continue;
       
   155 			}
       
   156 
       
   157 			// Get next argument
       
   158 			sTemp = GetStringUntilNextSpace( sRestOfLine );
       
   159 			// This might be process id or error message
       
   160 			if ( sTemp.compare( ERROR_OCCURED ) == 0 )
       
   161 			{
       
   162 				// Api mismatch between s60 side and atool.exe
       
   163 				if ( sRestOfLine.find( INCORRECT_ATOOL_VERSION ) != string::npos )
       
   164 				{
       
   165 					cout << "Test run failed because version conflict between device binaries\nand the atool.exe version used to build the application." << endl;
       
   166 					size_t pS = sRestOfLine.find_first_of('[');
       
   167 					size_t pE =  sRestOfLine.find_first_of(']');
       
   168 					size_t pSL = sRestOfLine.find_last_of('[');
       
   169 					size_t pEL = sRestOfLine.find_last_of(']');
       
   170 					if ( pS != string::npos && pE != string::npos && pSL != string::npos && pEL != string::npos )
       
   171 					{
       
   172 						string deviceVer = sRestOfLine.substr( pS+1, pE-pS-1 );
       
   173 						string atoolVer = sRestOfLine.substr( pSL+1, pEL-pSL-1 );
       
   174 						cout << "\tdevice: " << deviceVer << endl 
       
   175 							<<  "\tatool.exe: " << atoolVer << endl;
       
   176 					}
       
   177 				}
       
   178 				else
       
   179 					cout << sRestOfLine << endl;
       
   180 				continue;
       
   181 			}
       
   182 			unsigned long iProcessID = _httoi( sTemp.c_str() );
       
   183 
       
   184 			iProcessIDinList = -1;
       
   185 			// Find process from list
       
   186 			for( unsigned int i = 0 ; i < vProcessList.size() ; i++ )
       
   187 			{
       
   188 				if( vProcessList[i].iProcessID == iProcessID )
       
   189 				{
       
   190 					iProcessIDinList = i;
       
   191 					break;
       
   192 				}
       
   193 			}
       
   194 			// Is Process ID found from list?
       
   195 			if( iProcessIDinList == -1 )
       
   196 			{
       
   197 				CProcessData ProcessData;
       
   198 				ProcessData.bProcessOnGoing = false;
       
   199 				ProcessData.iProcessID = iProcessID;
       
   200 				vProcessList.push_back( ProcessData );
       
   201 				iProcessIDinList = (int)vProcessList.size() - 1;
       
   202 			}
       
   203 
       
   204 			// Remove spaces from end of line
       
   205 			while( sRestOfLine[sRestOfLine.size()-1] == ' ' )
       
   206 			{
       
   207 				sRestOfLine.resize( sRestOfLine.size()-1 );
       
   208 			}
       
   209 
       
   210 			string sWholeTempLine( sRestOfLine );
       
   211 
       
   212 			// Get command
       
   213 			sTemp = GetStringUntilNextSpace( sRestOfLine );
       
   214 
       
   215 			// Use c style string for easy comparisong of command.
       
   216 			const char* pCommand = sTemp.c_str();		
       
   217 
       
   218 			// Process start.
       
   219 			if( ! _stricmp( pCommand, LABEL_PROCESS_START ) )
       
   220 			{
       
   221 				bRet = true; // Set return value true we found start.
       
   222 				vProcessList[iProcessIDinList].vData.push_back( sWholeTempLine );
       
   223 				vProcessList[iProcessIDinList].bProcessOnGoing = true;
       
   224 				continue;
       
   225 			}
       
   226 
       
   227 			// Check is process ongoing if not skip other tags.
       
   228 			if( vProcessList[iProcessIDinList].bProcessOnGoing == false )
       
   229 				continue;
       
   230 
       
   231 			// "Old style" allocation (< v.1.6)
       
   232 			if( ! _stricmp( pCommand, ALLOC_ID ) )
       
   233 			{
       
   234 				// Add alloc
       
   235 				vProcessList[iProcessIDinList].Alloc( sRestOfLine );
       
   236 
       
   237 				// Subtests running?
       
   238 				vector<CSubTestData>::iterator viSubTestIter = vProcessList[iProcessIDinList].vSubTests.begin();
       
   239 				while( viSubTestIter != vProcessList[iProcessIDinList].vSubTests.end() )
       
   240 				{
       
   241 					if( viSubTestIter->bRunning )
       
   242 					{
       
   243 						// Save alloc also to sub test
       
   244 						viSubTestIter->Alloc( sRestOfLine );
       
   245 					}
       
   246 					viSubTestIter++;
       
   247 				}
       
   248 			}
       
   249 			else if ( ! _stricmp( pCommand, ALLOCH_ID ) )
       
   250 			{
       
   251 				// Add alloc
       
   252 				vProcessList[iProcessIDinList].AllocH( sRestOfLine );
       
   253 
       
   254 				// Subtests running?
       
   255 				vector<CSubTestData>::iterator viSubTestIter = vProcessList[iProcessIDinList].vSubTests.begin();
       
   256 				while( viSubTestIter != vProcessList[iProcessIDinList].vSubTests.end() )
       
   257 				{
       
   258 					if( viSubTestIter->bRunning )
       
   259 					{
       
   260 						// Save alloc also to sub test
       
   261 						viSubTestIter->AllocH( sRestOfLine );
       
   262 					}
       
   263 					viSubTestIter++;
       
   264 				}
       
   265 			}
       
   266 			// Allocation fragment (call stack).
       
   267 			else if ( ! _stricmp( pCommand, ALLOCF_ID ) )
       
   268 			{
       
   269 				// Add alloc fragment
       
   270 				vProcessList[iProcessIDinList].AllocF( sRestOfLine );
       
   271 				
       
   272 				// Subtests running?
       
   273 				vector<CSubTestData>::iterator viSubTestIter = vProcessList[iProcessIDinList].vSubTests.begin();
       
   274 				while( viSubTestIter != vProcessList[iProcessIDinList].vSubTests.end() )
       
   275 				{
       
   276 					if( viSubTestIter->bRunning )
       
   277 					{
       
   278 						// Save alloc fragment also to sub test
       
   279 						viSubTestIter->AllocF( sRestOfLine );
       
   280 					}
       
   281 					viSubTestIter++;
       
   282 				}
       
   283 			}
       
   284 			// Command free
       
   285 			else if( ! _stricmp( pCommand, FREE_ID ) )
       
   286 			{
       
   287 				// Send free
       
   288 				vProcessList[iProcessIDinList].Free( sRestOfLine );
       
   289 
       
   290 				// Subtests running?
       
   291 				vector<CSubTestData>::iterator viSubTestIter = vProcessList[iProcessIDinList].vSubTests.begin();
       
   292 				while( viSubTestIter != vProcessList[iProcessIDinList].vSubTests.end() )
       
   293 				{
       
   294 					if( viSubTestIter->bRunning )
       
   295 					{
       
   296 						// Send free to subtest
       
   297 						viSubTestIter->Free( sRestOfLine );
       
   298 					}
       
   299 					viSubTestIter++;
       
   300 				}
       
   301 			}
       
   302 			// Header free.
       
   303 			else if( ! _stricmp( pCommand, FREEH_ID ) )
       
   304 			{
       
   305 				// Send free
       
   306 				vProcessList[iProcessIDinList].FreeH( sRestOfLine );
       
   307 
       
   308 				// Subtests running?
       
   309 				vector<CSubTestData>::iterator viSubTestIter = vProcessList[iProcessIDinList].vSubTests.begin();
       
   310 				while( viSubTestIter != vProcessList[iProcessIDinList].vSubTests.end() )
       
   311 				{
       
   312 					if( viSubTestIter->bRunning )
       
   313 					{
       
   314 						// Send free to subtest
       
   315 						viSubTestIter->FreeH( sRestOfLine );
       
   316 					}
       
   317 					viSubTestIter++;
       
   318 				}
       
   319 			
       
   320 			}
       
   321 			else if( ! _stricmp( pCommand, FREEF_ID ) )
       
   322 			{
       
   323 				// Not used currently.
       
   324 			}
       
   325 			// Command process end
       
   326 			else if( ! _stricmp( pCommand, LABEL_PROCESS_END ) )
       
   327 			{
       
   328 				// Set process has ended.
       
   329 				vProcessList[iProcessIDinList].bProcessOnGoing = false;
       
   330 
       
   331 				// Save leaks
       
   332 				vector<string> vLeaks;
       
   333 				vector<string>::iterator viLeaks;
       
   334 				vProcessList[iProcessIDinList].GetLeakList( vLeaks );
       
   335 				for ( viLeaks = vLeaks.begin(); viLeaks != vLeaks.end(); viLeaks++ )
       
   336 				{
       
   337 					sTemp.clear();
       
   338 					sTemp.append( LABEL_MEM_LEAK );
       
   339 					sTemp.append( " " );
       
   340 					sTemp.append( *viLeaks );
       
   341 					vProcessList[iProcessIDinList].vData.push_back( sTemp );
       
   342 				}
       
   343 				vProcessList[iProcessIDinList].ClearAllocs();
       
   344 
       
   345 				vector<string>::iterator viHandleIter = vProcessList[iProcessIDinList].vHandleLeaks.begin();
       
   346 				// Print handle leaks
       
   347 				while( viHandleIter != vProcessList[iProcessIDinList].vHandleLeaks.end() )
       
   348 				{
       
   349 					sTemp.clear();
       
   350 					sTemp.append( viHandleIter->c_str() );
       
   351 					vProcessList[iProcessIDinList].vData.push_back( sTemp );
       
   352 					viHandleIter++;
       
   353 				}
       
   354 				// Clear handle leaks from list
       
   355 				vProcessList[iProcessIDinList].vHandleLeaks.clear();
       
   356 
       
   357 				vector<CSubTestData>::iterator viSubTestIter = vProcessList[iProcessIDinList].vSubTests.begin();
       
   358 				// Print sub test leaks
       
   359 				while( viSubTestIter != vProcessList[iProcessIDinList].vSubTests.end() )
       
   360 				{
       
   361 					// Print sub test start
       
   362 					string sLine( LABEL_TEST_START ); sLine.append( " " );
       
   363 					sLine.append( viSubTestIter->sStartTime ); sLine.append( " " );
       
   364 					sLine.append( viSubTestIter->sSubTestName ); sLine.append( " " );
       
   365 					sLine.append( viSubTestIter->sSubTestStartHandleCount );
       
   366 					vProcessList[iProcessIDinList].vData.push_back( sLine );
       
   367 					sLine.clear();
       
   368 
       
   369 					// DLL Loads.
       
   370 					for( vector<string>::iterator it = viSubTestIter->vData.begin();
       
   371 						it != viSubTestIter->vData.end(); it++ )
       
   372 					{
       
   373 						vProcessList[iProcessIDinList].vData.push_back( (*it) );
       
   374 					}
       
   375 
       
   376 					// Subtest leaks.
       
   377 					vector<string> vSubLeaks;
       
   378 					vector<string>::iterator viSubLeaks;
       
   379 					viSubTestIter->GetLeakList( vSubLeaks );
       
   380 					for ( viSubLeaks = vSubLeaks.begin(); viSubLeaks != vSubLeaks.end(); viSubLeaks++ )
       
   381 					{
       
   382 						sLine.append( LABEL_MEM_LEAK );
       
   383 						sLine.append( " " );
       
   384 						sLine.append( *viSubLeaks );
       
   385 						vProcessList[iProcessIDinList].vData.push_back( sLine );
       
   386 						sLine.clear();
       
   387 					}
       
   388 					viSubTestIter->ClearAllocs();
       
   389 
       
   390 					if( !viSubTestIter->sEndTime.empty() )
       
   391 					{
       
   392 						// Print sub test end
       
   393 						sLine.append( LABEL_TEST_END ); sLine.append( " " );
       
   394 						sLine.append( viSubTestIter->sEndTime ); sLine.append( " " );
       
   395 						sLine.append( viSubTestIter->sSubTestName ); sLine.append( " " );
       
   396 						sLine.append( viSubTestIter->sSubTestEndHandleCount );
       
   397 						vProcessList[iProcessIDinList].vData.push_back( sLine );
       
   398 					}
       
   399 					viSubTestIter++;
       
   400 				}
       
   401 
       
   402 				// Clear sub tests from list
       
   403 				vProcessList[iProcessIDinList].vSubTests.clear();
       
   404 				vProcessList[iProcessIDinList].vData.push_back( sWholeTempLine );
       
   405 			}
       
   406 			else if( ! _stricmp( pCommand, LABEL_HANDLE_LEAK ) )
       
   407 			{
       
   408 				// Make whole line
       
   409 				sTemp.append( " " );
       
   410 				sTemp.append( sRestOfLine );
       
   411 				vProcessList[iProcessIDinList].vHandleLeaks.push_back( sTemp );
       
   412 			}
       
   413 			else if( ! _stricmp( pCommand, LABEL_DLL_LOAD ) )
       
   414 			{
       
   415 				// Add module load to process data.
       
   416 				vProcessList[iProcessIDinList].vData.push_back( sWholeTempLine );
       
   417 				// Add module load to subtest data if test running.
       
   418 				for( vector<CSubTestData>::iterator it = vProcessList[iProcessIDinList].vSubTests.begin();
       
   419 					it != vProcessList[iProcessIDinList].vSubTests.end(); it++ )
       
   420 				{
       
   421 					if( it->bRunning )
       
   422 						it->vData.push_back( sWholeTempLine );
       
   423 				}
       
   424 
       
   425 			}
       
   426 			else if( ! _stricmp( pCommand, LABEL_DLL_UNLOAD ) )
       
   427 			{
       
   428 				// Add module load to process data.
       
   429 				vProcessList[iProcessIDinList].vData.push_back( sWholeTempLine );
       
   430 				// Add module unload to subtest data if test running.
       
   431 				for( vector<CSubTestData>::iterator it = vProcessList[iProcessIDinList].vSubTests.begin();
       
   432 					it != vProcessList[iProcessIDinList].vSubTests.end(); it++ )
       
   433 				{
       
   434 					if( it->bRunning )
       
   435 						it->vData.push_back( sWholeTempLine );
       
   436 				}
       
   437 			}
       
   438 			else if( sTemp.find( LABEL_LOGGING_CANCELLED ) != string::npos ||
       
   439 				     sTemp.find( LABEL_PROCESS_END ) != string::npos || sTemp.find( LABEL_ERROR_OCCURED ) != string::npos ||
       
   440 					 sTemp.find( LABEL_HANDLE_LEAK ) != string::npos )
       
   441 			{
       
   442 				vProcessList[iProcessIDinList].vData.push_back( sWholeTempLine );
       
   443 			}
       
   444 			else if( ! _stricmp( pCommand, LABEL_TEST_START ) )
       
   445 			{
       
   446 				bRet = true; // Set return value true we found start.
       
   447 				// Get sub test time
       
   448 				string sSubTestTime = GetStringUntilNextSpace( sRestOfLine );
       
   449 				// Get sub test name
       
   450 				string sSubTestName = GetStringUntilNextSpace( sRestOfLine );
       
   451 				// Get sub test start handle count
       
   452 				string sSubTestStartHandleCount = GetStringUntilNextSpace( sRestOfLine );
       
   453 
       
   454 				CSubTestData SubTestData;
       
   455 				SubTestData.bRunning = true;
       
   456 				SubTestData.sStartTime = sSubTestTime;
       
   457 				SubTestData.sSubTestName = sSubTestName;
       
   458 				SubTestData.sSubTestStartHandleCount = sSubTestStartHandleCount.c_str();
       
   459 
       
   460 				vProcessList[iProcessIDinList].vSubTests.push_back( SubTestData );
       
   461 			}
       
   462 			else if( ! _stricmp( pCommand, LABEL_TEST_END ) )
       
   463 			{
       
   464 				// Get sub test time
       
   465 				string sSubTestEnd = GetStringUntilNextSpace( sRestOfLine );
       
   466 				// Get sub test name
       
   467 				string sSubTestName = GetStringUntilNextSpace( sRestOfLine );
       
   468 				// Get sub test end handle count
       
   469 				string sSubTestEndHandleCount = GetStringUntilNextSpace( sRestOfLine );
       
   470 
       
   471 				// Find subtest
       
   472 				vector<CSubTestData>::iterator viSubTestIter = vProcessList[iProcessIDinList].vSubTests.begin();
       
   473 				while( viSubTestIter != vProcessList[iProcessIDinList].vSubTests.end() )
       
   474 				{
       
   475 					if( viSubTestIter->sSubTestName == sSubTestName && viSubTestIter->sEndTime.empty() )
       
   476 					{
       
   477 						viSubTestIter->sEndTime = sSubTestEnd;
       
   478 						viSubTestIter->bRunning = false;
       
   479 						viSubTestIter->sSubTestEndHandleCount = sSubTestEndHandleCount.c_str();
       
   480 					}
       
   481 					viSubTestIter++;
       
   482 				}
       
   483 			}
       
   484 		}
       
   485 	}
       
   486 
       
   487 	// Print all saved data from processes
       
   488 	for( unsigned int i = 0 ; i < vProcessList.size() ; i++ )
       
   489 	{
       
   490 		// Print saved lines
       
   491 		for( unsigned int iDataCounter = 0 ; iDataCounter < vProcessList[i].vData.size() ; iDataCounter++ )
       
   492 		{
       
   493 			m_DataSaver.AddString( vProcessList[i].vData[iDataCounter].c_str() );
       
   494 			m_DataSaver.AddLineToLast();
       
   495 		}
       
   496 
       
   497 		string sTemp;
       
   498 
       
   499 		// Save leaks
       
   500 		vector<string> vLeaks;
       
   501 		vector<string>::iterator viLeaks;
       
   502 		vProcessList[i].GetLeakList( vLeaks );
       
   503 		for ( viLeaks = vLeaks.begin(); viLeaks != vLeaks.end(); viLeaks++ )
       
   504 		{
       
   505 			sTemp.clear();
       
   506 			sTemp.append( LABEL_MEM_LEAK );
       
   507 			sTemp.append( " " );
       
   508 			sTemp.append( *viLeaks );
       
   509 			m_DataSaver.AddString( sTemp.c_str() );
       
   510 			m_DataSaver.AddLineToLast();
       
   511 		}
       
   512 
       
   513 		vector<string>::iterator viHandleIter = vProcessList[i].vHandleLeaks.begin();
       
   514 		// Print handle leaks, if there is data left, there was no process end.
       
   515 		while( viHandleIter != vProcessList[i].vHandleLeaks.end() )
       
   516 		{
       
   517 			sTemp.clear();
       
   518 			sTemp.append( viHandleIter->c_str() );
       
   519 			m_DataSaver.AddString( sTemp.c_str() );
       
   520 			m_DataSaver.AddLineToLast();
       
   521 			viHandleIter++;
       
   522 		}
       
   523 		vector<CSubTestData>::iterator viSubTestIter = vProcessList[i].vSubTests.begin();
       
   524 		// Print sub test data, if there is data left, there was no process end.
       
   525 		while( viSubTestIter != vProcessList[i].vSubTests.end() )
       
   526 		{
       
   527 			// Print sub test start
       
   528 			string sLine( LABEL_TEST_START ); sLine.append( " " );
       
   529 			sLine.append( viSubTestIter->sStartTime ); sLine.append( " " );
       
   530 			sLine.append( viSubTestIter->sSubTestName ); sLine.append( " " );
       
   531 			sLine.append( viSubTestIter->sSubTestStartHandleCount );
       
   532 			m_DataSaver.AddString( sLine.c_str() );
       
   533 			m_DataSaver.AddLineToLast();
       
   534 			sLine.clear();
       
   535 
       
   536 			// DLL Loads.
       
   537 			for( vector<string>::iterator it = viSubTestIter->vData.begin();
       
   538 				it != viSubTestIter->vData.end(); it++ )
       
   539 			{
       
   540 				m_DataSaver.AddString( (*it).c_str() );
       
   541 				m_DataSaver.AddLineToLast();
       
   542 			}
       
   543 
       
   544 			// Subtest leaks.
       
   545 			vector<string> vSubLeaks;
       
   546 			vector<string>::iterator viSubLeaks;
       
   547 			viSubTestIter->GetLeakList( vSubLeaks );
       
   548 			for ( viSubLeaks = vSubLeaks.begin(); viSubLeaks != vSubLeaks.end(); viSubLeaks++ )
       
   549 			{
       
   550 				sLine.append( LABEL_MEM_LEAK );
       
   551 				sLine.append( " " );
       
   552 				sLine.append( *viSubLeaks );
       
   553 				m_DataSaver.AddString( sLine.c_str() );
       
   554 				m_DataSaver.AddLineToLast();
       
   555 				sLine.clear();
       
   556 			}
       
   557 
       
   558 			// Print sub test end
       
   559 			sLine.append( LABEL_TEST_END ); sLine.append( " " );
       
   560 			sLine.append( viSubTestIter->sEndTime ); sLine.append( " " );
       
   561 			sLine.append( viSubTestIter->sSubTestName ); sLine.append( " " );
       
   562 			sLine.append( viSubTestIter->sSubTestEndHandleCount );
       
   563 			m_DataSaver.AddString( sLine.c_str() );
       
   564 			m_DataSaver.AddLineToLast();
       
   565 
       
   566 			viSubTestIter++;
       
   567 		}
       
   568 	}
       
   569 	// Save lines to file.
       
   570 	m_DataSaver.SaveLinesToFile( pOutputFileName, TEXT_DATA );
       
   571 	// Close file.
       
   572 	in.close();
       
   573 	return bRet;
       
   574 }
       
   575 
       
   576 // -----------------------------------------------------------------------------
       
   577 // CATParseTraceFile::GetDataSaver
       
   578 // Gets data saver object.
       
   579 // -----------------------------------------------------------------------------
       
   580 CATDataSaver* CATParseTraceFile::GetDataSaver(void)	
       
   581 {
       
   582 	LOG_LOW_FUNC_ENTRY("CATParseTraceFile::GetDataSaver");
       
   583 	return &m_DataSaver;
       
   584 }
       
   585 //EOF