searcher/tsrc/robustnesstest/src/crobustnesstest.cpp
changeset 0 671dee74050a
child 23 d4d56f5e7c55
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/searcher/tsrc/robustnesstest/src/crobustnesstest.cpp	Mon Apr 19 14:40:16 2010 +0300
@@ -0,0 +1,457 @@
+/*
+* Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of "Eclipse Public License v1.0"
+* which accompanies this distribution, and is available
+* at the URL "http://www.eclipse.org/legal/epl-v10.html".
+*
+* Initial Contributors:
+* Nokia Corporation - initial contribution.
+*
+* Contributors:
+*
+* Description: 
+*
+*/
+
+#include "CRobustnessTest.h"
+#include "SearchServerCommon.h"
+#include "CStressWorker.h"
+#include "CLog.h"
+#include "RSearchServerSession.h"
+
+#include "SearchServerTesting.h"
+
+_LIT( KLogFile, 		"c:\\Data\\robustness\\log.txt" ); 
+_LIT( KRecordFile, 		"c:\\Data\\robustness\\record.csv" ); 
+_LIT( KTempRecordFile,	"c:\\Data\\robustness\\_record.csv" );
+//_LIT( KReportFile, 		"c:\\Data\\robustness\\report.txt" ); 
+_LIT( KConfigFile, 		"c:\\Data\\robustness\\config.txt" ); 
+
+CRobustnessTest::CRobustnessTest( CConsoleBase& aConsole,
+								  MRobustnessTestObserver& aObserver )
+:	iConsole( aConsole ),
+    iOwnedLog( 0 ),
+    iObserver( aObserver  ),
+	iPeriodic( 0 ), 
+    iSearchServerMonitor( 0 ),
+    iStressWorker( 0 ),
+	iTick( 0 )
+	{
+	}
+
+void CRobustnessTest::ConstructL( ) 
+	{
+	User::LeaveIfError( iFs.Connect() ); 
+	ConfigureL(); 
+
+	iSearchServerMonitor = 
+		new ( ELeave ) CProcessMonitor();
+	iStressWorker = new ( ELeave ) CStressWorker( iLog, 
+												  iPreIndex, 
+												  iIndexAverageItems,
+												  iIndexingEnabled, 
+												  iDeletesEnabled,
+												  iSearchersEnabled, 
+												  iCancellingEnabled,
+												  iIndexerSleep, 
+												  iSearcherSleep ); 
+	
+	iPeriodic = CPeriodic::NewL( EPriorityNormal ); 
+	}
+
+TInt CRobustnessTest::ReadNumberL( TPtrC8& left )
+	{
+	while ( ETrue )
+		{
+		// Try to find end of line 
+		TInt eol = left.Find( _L8( "\n" ) );
+		if ( eol < 0 ) User::Leave( KErrNotFound ); 
+
+		TPtrC8 line = left.Left( eol ); 
+		left.Set( left.Mid(eol+1) ); 
+		
+		TLex8 lex; 
+		lex.Assign( line ); 
+		lex.SkipSpace();
+		if ( !lex.Eos() && lex.Peek() != '#' ) 
+			{
+			TInt ret; 
+			lex.Val( ret );
+			return ret; 
+			}
+		}
+	}
+
+void CRobustnessTest::ConfigureL()
+	{
+	iTickCount = 15;
+	iTickLengthSeconds = 60; // 1 minute
+	iPreIndex = 0; 
+	iIndexAverageItems = 1000;  
+	iIndexingEnabled = ETrue; 
+	iDeletesEnabled = ETrue; 
+	iSearchersEnabled = ETrue; 
+	iCancellingEnabled = ETrue; 
+	iIndexerSleep = 100;  
+	iSearcherSleep = 20;  
+
+	RFile file; 
+	if ( file.Open( iFs, KConfigFile, EFileRead ) == KErrNone ) 
+		{
+		CleanupClosePushL( file );
+	
+		TInt size; 
+		file.Size( size ); 
+		
+		HBufC8* config = HBufC8::NewLC( size );
+		TPtr8 des( config->Des() );
+		User::LeaveIfError( file.Read( 0, des, size ) );  
+		
+		TPtrC8 loc = *config;
+	
+		iTickCount = ReadNumberL( loc ); 
+		iTickLengthSeconds = ReadNumberL( loc ); 
+		iPreIndex = ReadNumberL( loc );
+		iIndexAverageItems = ReadNumberL( loc );
+		iIndexingEnabled = ReadNumberL( loc ); 
+		iDeletesEnabled = ReadNumberL( loc ); 
+		iSearchersEnabled = ReadNumberL( loc ); 
+		iCancellingEnabled = ReadNumberL( loc ); 
+		iIndexerSleep = ReadNumberL( loc ); 
+		iSearcherSleep = ReadNumberL( loc ); 
+
+		CleanupStack::PopAndDestroy( config ); 
+		CleanupStack::PopAndDestroy(); // file;
+		}
+	}
+
+
+void CRobustnessTest::StartL()
+	{
+	// 
+	// Step 0: Start logging
+	iOwnedLog = CFileConsoleLog::NewL( &iConsole, KLogFile );
+	iLog.SetLog( *iOwnedLog );  
+	
+	// 
+	// Step 1. Fire up the search server
+	RSearchServerSession session; 
+	User::LeaveIfError( session.Connect() ); 
+	session.Close(); 
+	
+	// 
+	// Step 2. Start monitoring the search server
+	iSearchServerMonitor->StartL( *this, KSearchServerName ); 
+	
+	//
+	// Step 3. Clear old log and request search server to record RAM usage
+	iFs.Delete( KServerRecordFile ); // ignore errors
+	iFs.Delete( KRecordFile ); // ignore errors
+	iFs.Delete( KTempRecordFile ); // ignore errors
+	AddStatsLabelsL(); // prepare our own statistics record
+	
+	RFile file; 
+	iFs.MkDirAll( KStartRecordingSignalFile ); 
+	User::LeaveIfError( file.Create( iFs, KStartRecordingSignalFile, EFileWrite ) );
+	file.Close(); 
+	
+	//
+	// Step 4. Start stressing the search searver
+	iStressWorker->StartL();
+	
+	//
+	// Step 5. Set up the clock for checking reports and ending experiment
+	TTimeIntervalMicroSeconds32 tickInterval( 1000*1000*iTickLengthSeconds );
+	iPeriodic->Start( tickInterval, 
+					  tickInterval,
+					  TCallBack( CRobustnessTest::CallTick, this ) );
+	
+	//
+	// We are done
+	iLog.LogL( _L( "started" ) ); 
+	}
+
+CRobustnessTest::~CRobustnessTest()
+	{
+	iFs.Close();
+	
+	if ( iPeriodic ) 
+		{
+		iPeriodic->Cancel(); 
+		delete iPeriodic; 
+		}
+	if ( iSearchServerMonitor ) 
+		{
+		iSearchServerMonitor->Cancel(); 
+		delete iSearchServerMonitor; 
+		}
+	if ( iStressWorker  ) 
+		{
+		if ( iStressWorker->IsActive() ) iStressWorker->Finish(); 
+		delete iStressWorker; 
+		}
+	delete iOwnedLog; 
+	}
+
+namespace 
+	{
+	TPtrC8 ReadLineL( TPtrC8& loc )
+		{
+		TInt linefeed = loc.Find( _L8("\n") );
+		if ( linefeed < 0 ) 
+			{
+			return loc.Right( 0 );
+			}
+	
+		TPtrC8 ret( loc.Left( linefeed ) ); 
+		loc.Set( loc.Mid( linefeed + 1 ) ); 
+		return ret; 
+		}
+	}
+
+
+void CRobustnessTest::FinalizeRecordsL()
+	{
+	// Simply merge line by line
+	RFile test;
+	User::LeaveIfError( test.Open( iFs, KTempRecordFile, EFileRead ) );
+	CleanupClosePushL( test ); 
+
+	RFile server;
+	User::LeaveIfError( server.Open( iFs, KServerRecordFile, EFileRead ) );
+	CleanupClosePushL( server ); 
+
+	RFile target;
+	User::LeaveIfError( target.Create( iFs, KRecordFile, EFileWrite ) );
+	CleanupClosePushL( target ); 
+	
+	HBufC8* testBuf = HBufC8::NewLC( 2048 );
+	HBufC8* serverBuf = HBufC8::NewLC( 2048 );
+
+	TPtr8 testBufDes = testBuf->Des();
+	test.Read( testBufDes ); 
+	TPtr8 serverBufDes = serverBuf->Des();
+	server.Read( serverBufDes ); 
+	
+	TPtrC8 testLoc = *testBuf; 
+	TPtrC8 serverLoc = *serverBuf; 
+	
+	for ( TInt i = 0; i < iTick; i++ )
+		{
+		TPtrC8 testLine = ReadLineL( testLoc ); 
+		TPtrC8 serverLine = ReadLineL( serverLoc ); 
+		
+		target.Write( testLine ); 
+		target.Write( serverLine ); 
+		target.Write( _L8( "\n" ) ); 
+		}
+	
+	target.Flush(); 
+		
+	CleanupStack::PopAndDestroy( serverBuf ); 
+	CleanupStack::PopAndDestroy( testBuf ); 
+	
+	CleanupStack::PopAndDestroy( 3 ); // target, server, test
+	}
+
+
+void CRobustnessTest::AppendRecordL( RPointerArray<HBufC8>& aStats )
+	{
+	RFile file;
+	TInt err = file.Open( iFs, KTempRecordFile, EFileWrite );
+	if ( err == KErrNotFound ) 
+		{
+		err = file.Create( iFs, KTempRecordFile, EFileWrite );
+		} 
+	User::LeaveIfError( err ); 
+	CleanupClosePushL( file ); 
+
+	TInt end = 0;
+	file.Seek( ESeekEnd, end );
+	
+	TInt defaultWidth = 8;
+	
+	for ( TInt i = 0; i < aStats.Count(); i++ ) 
+		{
+		file.Write( *aStats[i] );
+		TInt spaces = Max( 0, defaultWidth - aStats[i]->Length() );
+		for ( TInt j = 0; j < spaces; j++ )
+			{
+			file.Write( _L8( " " ) );
+			}
+		file.Write( _L8( "; " ) );
+		}
+	file.Write( _L8( "\n" ) );
+		
+	file.Flush();
+	CleanupStack::PopAndDestroy(); // file
+	}
+
+void CRobustnessTest::AddStatsLabelsL() 
+	{
+	RPointerArray<HBufC8> stats; 
+	
+	TRAPD( err, stats.Append( _L8( "tick" ).AllocL() ) );
+	
+	if ( err == KErrNone ) 
+		TRAP( err, iStressWorker->AppendStatsLabelsL( stats ) ); 
+	
+	if ( err == KErrNone ) 
+		TRAP( err, AppendRecordL( stats ) ); 
+	
+	if ( err != KErrNone )
+		iLog.LogL( _L( "adding labels failed") ); 
+	
+	stats.ResetAndDestroy();
+	stats.Close(); 
+	}
+
+void CRobustnessTest::AddStatsEntryL() 
+	{
+	RPointerArray<HBufC8> stats; 
+
+	TRAPD( err, 
+		HBufC8* buf = HBufC8::NewL( 32 );
+		buf->Des().AppendNum( iTick ); 
+		stats.Append( buf ) 
+		);
+	
+	if ( err == KErrNone ) 
+		TRAP( err, iStressWorker->AppendStatsL( stats ) ); 
+	
+	if ( err == KErrNone ) 
+		TRAP( err, AppendRecordL( stats ) ); 
+		
+	if ( err != KErrNone )
+		iLog.LogL( _L( "adding stats failed") ); 
+		
+	stats.ResetAndDestroy();
+	stats.Close(); 
+	}
+
+void CRobustnessTest::Tick() 
+	{
+	if ( iTick++ < iTickCount ) 
+		{
+		TRAP_IGNORE( iLog.LogL( _L( "tick") ) );
+
+		TInt err;
+		// 
+		// Request server to dump performance record
+		TRAP( err, AddStatsEntryL() );
+		if ( err != KErrNone ) 
+			{
+			TRAP_IGNORE( iLog.LogL( _L( "adding record failed" ) ) );
+			}
+		
+		RFile file;
+		err = file.Create( iFs, KDumpRecordSignalFile, EFileWrite );
+		if ( err == KErrNone ) 
+			{
+			file.Close();
+			}
+		else 
+			{
+			TRAP_IGNORE( iLog.LogL( _L( "requesting server record failed" ) ) );
+			}
+		
+		TRAP( err, iStressWorker->ReportL() );  
+		if ( err != KErrNone ) 
+			{
+			TRAP_IGNORE( iLog.LogL( _L( "adding record failed" ) ) );
+			}
+		}
+	else 
+		{
+		TRAPD( err, 
+			iPeriodic->Cancel();
+			iLog.LogL( _L( "shutting down" ) );
+			User::LeaveIfError( iStressWorker->Finish() ); 
+			User::LeaveIfError( iFs.Connect() );
+			RFile file; 
+			User::LeaveIfError( file.Create( iFs, KDumpRecordSignalFile, EFileWrite ) );
+			file.Close(); 
+			User::LeaveIfError( file.Create( iFs, KStopRecordingSignalFile, EFileWrite ) );
+			file.Close(); 
+			User::LeaveIfError( file.Create( iFs, KShutdownSignalFile, EFileWrite ) );
+			file.Close(); 
+		);
+		if ( err != KErrNone ) 
+			{
+			TRAP_IGNORE( iLog.LogL( _L( "failed with %d" ), err ) ); 
+						
+			TRAP_IGNORE( FinishL() ); 
+			}
+		}
+	}
+
+TInt CRobustnessTest::CallTick(TAny* aThis)
+	{
+	reinterpret_cast<CRobustnessTest*>(aThis)->Tick(); 
+	return KErrNone; 
+	}
+
+void CRobustnessTest::FinishL() 
+	{
+	if ( iPeriodic )  			iPeriodic->Cancel(); 
+	if ( iStressWorker ) 		iStressWorker->Finish(); 
+	if ( iSearchServerMonitor ) iSearchServerMonitor->Cancel(); 
+
+	TRAPD(err,  
+		// Create a brand new record file by merging the server record
+		// with the robustness test record
+		iFs.Delete( KRecordFile ); 
+		FinalizeRecordsL(); 
+		iFs.Delete( KTempRecordFile ); 
+	);
+	if ( err != KErrNone ) 
+		TRAP_IGNORE( iLog.LogL( _L( "finalizing record failed (%d)" ), err ); ); 
+	
+	if ( iTick == ( iTickCount+1 ) )
+		{
+		TRAP_IGNORE( iLog.LogL( _L( "finished") ) ); 
+		}
+	else 
+		{
+		TRAP_IGNORE( iLog.LogL( _L( "interrupted by server termination") ) ); 
+		TRAP_IGNORE( iLog.LogL( _L( "failed") ) ); 
+		}
+
+
+	iObserver.FinishedL( *this );
+	}
+	
+void CRobustnessTest::ProcessFinished( CProcessMonitor& aMonitor, 
+									   TExitType aExitType ,
+									   TExitCategoryName aCategory,
+									   TInt aExitReason ) 
+	{
+	switch ( aExitType ) 
+		{
+		case EExitKill:
+			iLog.LogL( _L( "%S shut down." ), &aMonitor.ProcessName() ); 
+			break;
+		case EExitTerminate: 
+			iLog.LogL( _L( "%S terminated." ), &aMonitor.ProcessName() ); 
+			break;
+		case EExitPanic: 
+			iLog.LogL( _L( "%S paniced %S %d." ), 
+						&aMonitor.ProcessName(), 
+						&aCategory,
+						aExitReason ); 
+			break;
+		}
+	FinishL(); 
+	}
+
+void CRobustnessTest::Failed( CProcessMonitor& aMonitor,
+							  TInt aError ) 
+	{
+	iLog.LogL( _L( "Monitoring %S failed with %d." ), 
+			   &aMonitor.ProcessName(),
+			   aError ); 
+	FinishL(); 
+	}
+